package ru.amse.tsyganov.jumleditor.view.repr;

import java.util.List;

import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;

import ru.amse.tsyganov.jumleditor.graphicaleditor.Coordinates;
import ru.amse.tsyganov.jumleditor.model.ActivityGraph;
import ru.amse.tsyganov.jumleditor.model.ModelElement;
import ru.amse.tsyganov.jumleditor.properties.PropertiesList;
import ru.amse.tsyganov.jumleditor.properties.Property;
import ru.amse.tsyganov.jumleditor.properties.PropertyChangeListener;
import ru.amse.tsyganov.jumleditor.properties.StringProperty;
import ru.amse.tsyganov.jumleditor.validator.Problem;
import ru.amse.tsyganov.jumleditor.view.ModelViewMap;
import ru.amse.tsyganov.jumleditor.view.SelectedItems;
import ru.amse.tsyganov.jumleditor.view.Validity;
import ru.amse.tsyganov.jumleditor.view.ViewVisitor;
import ru.amse.tsyganov.jumleditor.view.activepoints.ActivePoint;

public abstract class ViewElement<T extends ModelElement> {
	
	private final T model;
	
	private final PropertiesList properties = new PropertiesList();
	
	private Validity validity = Validity.NORMAL;
	
	public ViewElement(T model) {
		if (model == null) {
			throw new IllegalArgumentException();
		}
		this.model = model;
	}
	
	public final T getModel() {
		assert model != null;
		return model;
	}
	
	public ModelViewMap getModelViewMap() {
		return getActivityGraphView().getModelViewMap();
	}
	
	public SelectedItems getSelectedItems() {
		return getActivityGraphView().getSelectedItems();
	}
	
	public abstract void accept(ViewVisitor v);
	
	public abstract void paint(GC gc, Coordinates coordinates);
	
	public abstract void paintActivePoints(GC gc, Coordinates coordinates);
	
	public abstract List<? extends ActivePoint> getActivePoints();
	
	public abstract ActivityGraphView<? extends ActivityGraph> getActivityGraphView();
	
	public PropertiesList getProperties() {
		return properties;
	}
	
	public abstract StringProperty getMainProperty();
	
	public abstract Point getGuardOutputPoint();
	
	public void addPropertyListener(PropertyChangeListener listener) {
		for (Property p : getProperties().getList()) {
			p.addChangeListener(listener);
		}
	}
	
	public void removePropertyListener(PropertyChangeListener listener) {
		for (Property p : getProperties().getList()) {
			p.removeChangeListener(listener);
		}
	}
	
	public final Validity getValidity() {
		return validity;
	}

	public abstract List<Problem> getInnerProblems();

	public void setValidity(Validity validity) {
		this.validity = validity;
	}
	
	public abstract String getClassName();
}
